﻿using System;
using System.Linq;
using NUnit.Framework;
using TypeMock.ArrangeActAssert;

namespace TypeMockDemo.Fixtures
{
    [TestFixture]
    [Category("Domain.Isolated")]
    public sealed class PersonFixture
    {
        [Test]
        [Category("Domain.Isolated")]
        public void AssertThatCanCreateANewPerson()
        {
            Person person = Isolate.Fake.Instance<Person>();
            Assert.That(person, Is.Not.Null);
        }

        [Test]
        [Category("Domain.Isolated")]
        public void AssertThatCanCreateANewEmployee()
        {
            Person person = Isolate.Fake.Instance<Employee>();
            Assert.That(person, Is.Not.Null);
        }

        [Test]
        [Category("Domain.Isolated")]
        public void AssertThatCanCreateANewCustomer()
        {
            Person person = Isolate.Fake.Instance<Customer>();
            Assert.That(person, Is.Not.Null);
        }

        [Test]
        [Category("Domain.Isolated")]
        public void AssertThatCannotAddTheSameAddressTwice()
        {
            Person person = Isolate.Fake.Instance<Person>(Members.CallOriginal, ConstructorWillBe.Called);
            Address address = Isolate.Fake.Instance<Address>();
            person.AddAddress(address);
            Assert.That(person.Addresses.Count(), Is.EqualTo(1));
            Assert.Throws<InvalidOperationException>(() => person.AddAddress(address));
        }
        [Test]
        [Category("Domain.Isolated")]
        public void AssertThatCannotRemoveTheSameAddressTwice()
        {
            Person person = Isolate.Fake.Instance<Person>(Members.CallOriginal, ConstructorWillBe.Called);
            Address address = Isolate.Fake.Instance<Address>();
            person.AddAddress(address);
            Assert.That(person.Addresses.Count(), Is.EqualTo(1));
            person.RemoveAddress(address);
            Assert.Throws<InvalidOperationException>(() => person.RemoveAddress(address));
        }

        [Test]
        [Category("Domain.Isolated")]
        public void AssertThatWhenCreateAnAddressTheParentPersonIsInjected()
        {
            Person person = Isolate.Fake.Instance<Person>(Members.CallOriginal, ConstructorWillBe.Called);
            Address address = Isolate.Fake.Instance<Address>(Members.CallOriginal, ConstructorWillBe.Called, person);
            
            Assert.That(person, Is.Not.Null);
            Assert.That(address, Is.Not.Null);
            Assert.That(address, Has.Property("Person").EqualTo(person));
        }
    }
}